﻿using DirectoryServicesProtocolsExtensions.MetaData;

namespace DirectoryServicesProtocolsExtensions.SearchRequest
{
    using System;
    using System.Collections.Generic;
    using System.DirectoryServices.Protocols;
    using System.Linq;
    using System.Text;
    using LdapConnection.MetaData;
    using LdapConnection;

    public static class Validation
    {
        public static void PreExecuteTest(
            this SearchRequest searchRequest,
            LdapConnection ldapConnection,
            LdapMetaMapFactory ldapMetaMapFactory)
        {
            List<string> undefinedAttributes;
            TestConnectionToBaseDN(searchRequest, ldapConnection);
            AreSuppliedAttributesDefinedInSchema(
                searchRequest,
                ldapConnection,
                ldapMetaMapFactory,
                out undefinedAttributes);
        }

        public static void TestConnectionToBaseDN(
            this SearchRequest searchRequest,
            LdapConnection ldapConnection)
        {
            var testSearchRequest = new SearchRequest
            {
                DistinguishedName = searchRequest.DistinguishedName,
                Scope = SearchScope.Base
            };

            var searchResponse = (SearchResponse)ldapConnection.SendRequest(testSearchRequest);
            if (searchResponse != null && searchResponse.ErrorMessage !=null)
            {
                throw new Exception(
                    string.Format("{0} Base DN specified in the query could not be located", searchRequest.DistinguishedName));
            }
        }

        public static void AreSuppliedAttributesDefinedInSchema(
            this SearchRequest searchRequest,
            LdapConnection ldapConnection,
            LdapMetaMapFactory ldapMetaMapFactory,
            out List<string> undefinedAttributes)
        {
            undefinedAttributes = searchRequest
                .Attributes
                .Cast<string>()
                .Where(attribute => ldapConnection.GetAttributeMetaData(attribute, ldapMetaMapFactory) == null)
                .ToList();

            if (undefinedAttributes.Count != 0)
            {
                var exceptionMessage = new StringBuilder();
                exceptionMessage.Append(
                    "Some attributesToLoad specified in the query could not be found in the Active Directory Schema (");
                foreach (var undefinedAttribute in undefinedAttributes)
                {
                    exceptionMessage.Append(undefinedAttribute + " ");
                }
                exceptionMessage.Append(")");
                throw new Exception(exceptionMessage.ToString());
            }
        }
    }
}
